package threadingexercise;


import java.util.concurrent.PriorityBlockingQueue;

// 表示一个任务
// 注意写上比较规则
class MyTask implements Comparable<MyTask>{
    public Runnable runnable;

    //为了后续的判定，使用绝对的时间戳
    public long time;

    public MyTask(Runnable runnable , long delay) {
        this.runnable = runnable;
        //取当前时刻的时间戳 + delay ，作为该任务实际执行的时间戳
        this.time = System.currentTimeMillis() + delay;
    }

    @Override
    public int compareTo(MyTask o) {
        //每次去出的是时间最小的元素，谁减谁 带入元素试一下就行了
        return (int)(this.time - o.time);
    }
}


class MyTimer {
    //带有优先级的阻塞队列
    private PriorityBlockingQueue<MyTask> queue = new PriorityBlockingQueue();

    public void schedule(Runnable runnable , long delay) {
        //根据参数，构造MyTask，在插入队列即可
        MyTask myTask = new MyTask(runnable,delay);
        queue.put(myTask);

        //每次放一个任务，就唤醒wait，同时这里也要加上锁
        synchronized(locker) {
            locker.notify();
        }
    }

    //创建一个锁对象 , 作用就是为了判断 不同的锁 锁的对象是不是同一个
    Object locker = new Object();

    public MyTimer() {

//        //根据参数，构造MyTask，在插入队列即可
//        MyTask myTask = new MyTask(runnable,delay);
//        queue.put(myTask);
//
//        //每次放一个任务，就唤醒wait，同时这里也要加上锁
//        synchronized(locker) {
//            locker.notify();
//        }

        Thread t = new Thread(() -> {
            while(true) {
                //取元素
                try {
                    synchronized(locker) {
                        MyTask myTask = queue.take();
                        long curTime = System.currentTimeMillis();
                        if(myTask.time <= curTime ) {
                            //表示任务到了   14:00 <= 14：20
                            //这里为什么要加 run()?  没有run() 报错
                            myTask.runnable.run();
                        }else {
                            //时间还没到
                            //把刚才娶回来的任务，再放回去，此队列没有peek
                            //再加上一个等待时间
                            queue.put(myTask);
                            locker.wait( myTask.time - curTime );  //需要搭配 锁 来使用wait
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        t.start();
    }
}

//模拟实现定时器
public class ThreadDemo23TimerSimulation {
    public static void main(String[] args) {
//        MyTimer myTimer = new MyTimer(new Runnable() {
//            @Override
//            public void run() {
//                System.out.println("hello3");
//            }
//        },3000);



        MyTimer myTimer = new MyTimer();
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello3");
            }
        },3000);

        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello2");
            }
        },2000);


        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello1");
            }
        },1000);

        System.out.println("hello");
    }
}
